package com.zunipe.accounts;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.PopupMenu;
import android.widget.Spinner;
import android.widget.Toast;

import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;

import com.zunipe.accounts.database.entity.Account;
import com.zunipe.accounts.database.handler.AccountHandler;
import com.zunipe.accounts.databinding.ActivityMainBinding;
import com.zunipe.accounts.fragment.AccountFragment;
import com.zunipe.accounts.fragment.PersonalFragment;
import com.zunipe.accounts.util.DateUtils;

import java.time.LocalDate;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Set;

public class MainActivity extends AppCompatActivity {
    ActivityMainBinding binding;
    private FragmentManager fragmentManager;
    private Set<Fragment> fragmentSet;
    private AccountFragment accountFragment;
    private PersonalFragment personalFragment;
    private AccountHandler accountHandler;
    private static final int FLAG_EXPENSES = 0;
    private static final int FLAG_INCOME = 1;
    private static final int FLAG_EDIT_EXPENSES = 2;
    private static final int FLAG_EDIT_INCOME = 3;
    private BroadcastReceiver broadcastReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        setSupportActionBar(binding.toolbar);
        // 初始化Fragment
        initFragment();

        accountHandler = new AccountHandler();

        broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                int id = intent.getIntExtra("id", 0);
                String type = intent.getStringExtra("type");
                if (type != null) {
                    if (type.equals("income")) {
                        showAccountDialog(FLAG_EDIT_INCOME, id);
                    } else {
                        showAccountDialog(FLAG_EDIT_EXPENSES, id);
                    }
                }
            }
        };
        registerReceiver(broadcastReceiver, new IntentFilter("com.zunipe.accounts.open.edit.dialog"), RECEIVER_NOT_EXPORTED);

        binding.btnNewAccount.setOnClickListener(v -> {
            PopupMenu popup = new PopupMenu(this, v);
            popup.getMenuInflater().inflate(R.menu.popup_menu, popup.getMenu());

            popup.setOnMenuItemClickListener(item -> {
                int id = item.getItemId();
                if (id == R.id.expenses) {
                    showAccountDialog(FLAG_EXPENSES, 0);
                } else {
                    showAccountDialog(FLAG_INCOME, 0);
                }
                return true;
            });

            popup.show();
        });

        binding.navBar.setOnItemSelectedListener(item -> {
            int id = item.getItemId();
            if (id == R.id.nav_account) {
                showFragment(accountFragment);
            } else if (id == R.id.nav_personal) {
                showFragment(personalFragment);
            }
            return true;
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (broadcastReceiver != null) {
            unregisterReceiver(broadcastReceiver);
        }
    }

    private void showAccountDialog(int flag, int id) {
        int layoutId = 0;
        switch (flag) {
            case FLAG_EXPENSES:
            case FLAG_EDIT_EXPENSES:
                layoutId = R.array.account_expenses_options;
                break;
            case FLAG_INCOME:
            case FLAG_EDIT_INCOME:
                layoutId = R.array.account_income_options;
                break;
        }
        if (layoutId == 0)
            return;
        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
                this,
                layoutId,
                android.R.layout.simple_spinner_item
        );
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        View view = getLayoutInflater().inflate(R.layout.account_dialog_layout, null);
        Spinner spinner = view.findViewById(R.id.sp_type);
        spinner.setAdapter(adapter);
        EditText etAmount = view.findViewById(R.id.et_amount);
        EditText etNote = view.findViewById(R.id.et_note);
        DatePicker datePicker = view.findViewById(R.id.datePicker);
        if (flag >= FLAG_EDIT_EXPENSES) {
            Account account = accountHandler.getAccountById(id);
            etAmount.setText(String.valueOf(account.getAmount() * (flag == FLAG_EDIT_EXPENSES ? -1 : 1)));
            LocalDate localDate = LocalDate.parse(account.getDate());
            datePicker.updateDate(localDate.getYear(), localDate.getMonth().getValue() - 1, localDate.getDayOfMonth());
            if (account.getNotes() != null) {
                etNote.setText(account.getNotes());
            }
            if (flag == FLAG_EDIT_EXPENSES) {
                spinner.setSelection(AccountApplication.getInstance().getExpensesTypeIndex(account.getType()));
            } else {
                spinner.setSelection(AccountApplication.getInstance().getIncomeTypeIndex(account.getType()));
            }
        }
        AlertDialog dialog = new AlertDialog.Builder(this)
                .setTitle(flag == 0 ? "新建支出账单" : "新建收入账单")
                .setView(view)
                .setPositiveButton("确定", (dialog1, which) -> {
                    String amount = etAmount.getText().toString();
                    String note = etNote.getText().toString();
                    Calendar calendar = Calendar.getInstance();
                    calendar.set(Calendar.YEAR, datePicker.getYear());
                    calendar.set(Calendar.MONTH, datePicker.getMonth());
                    calendar.set(Calendar.DAY_OF_MONTH, datePicker.getDayOfMonth());
                    if (amount.isEmpty()) {
                        Toast.makeText(this, "请输入金额", Toast.LENGTH_SHORT).show();
                        return;
                    }
                    Account account = new Account();
                    account.setAmount(Double.parseDouble(amount) * (flag == 0 ? -1 : 1));
                    account.setDate(DateUtils.getDay(calendar.getTimeInMillis()));
                    account.setType(spinner.getSelectedItem().toString());
                    account.setUserId(AccountApplication.getInstance().getUserId());
                    if (!note.isEmpty())
                        account.setNotes(note);
                    if (flag >= FLAG_EDIT_EXPENSES) {
                        account.setId(id);
                        accountHandler.updateAccount(account);
                    } else {
                        accountHandler.addAccount(account);
                    }
                    accountFragment.update();
                })
                .setNegativeButton("取消", null)
                .create();
        dialog.show();
    }

    private void initFragment() {
        fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        fragmentSet = new HashSet<>();
        accountFragment = new AccountFragment();
        personalFragment = new PersonalFragment();
        transaction.add(R.id.main_layout, accountFragment);
        transaction.add(R.id.main_layout, personalFragment);
        fragmentSet.add(accountFragment);
        fragmentSet.add(personalFragment);
        transaction.commit();
        showFragment(accountFragment);
    }

    private void showFragment(Fragment fragment) {
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        fragmentSet.forEach(transaction::hide);
        transaction.show(fragment);
        transaction.commit();
    }
}